package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.article.IArticleClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmChannelSevice;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 10161
 */
@Service
@Transactional
@Slf4j
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private WmChannelSevice wmChannelSevice;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Override
    public void textAutoScan(Integer newsId) {
        //1.根据NewsId 查出content
        WmNews resultNews = wmNewsService.getById(newsId);

        if (resultNews==null) {
            //查不到文章，抛出个异常
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章不存在");
        }
        //当news的status是 1 （submit，提交待审）的时候才进行我们的审核业务
        if (resultNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) {
            //2.将获取到的content发送到aliyun接口进行审核
            String content = resultNews.getContent();
            //2.1对contentjson字符串进行处理提取 提取出图片和文本
            StringBuilder scanText = new StringBuilder();
            List<byte[]>imageList = new ArrayList<>();
            List<Map> maps = JSON.parseArray(content, Map.class);
            for (Map map : maps) {
                if (map.get("type").equals("text")) {
                    //把为text的内容提取出来
                    scanText.append((String) map.get("value"));
                }
                //处理text就是image了
                byte[] values = fileStorageService.downloadFile((String) map.get("value"));
                imageList.add(values);
            }
            //3.判断审核结果是否通过，不通过直接return
            if (!handleTextScan(resultNews,content)){
                return;
            }
            if (!handleImageScan(resultNews,imageList)){
                return;
            }
            //4.审核通过，设置将通过审核的news保存到app端的article中
            ResponseResult responseResult = saveAppArticle(resultNews);
            if(!responseResult.getCode().equals(200)){
                throw new RuntimeException("WmNewsAutoScanServiceImpl-文章审核，保存app端相关文章数据失败");
            }
            //回填article_id
            resultNews.setArticleId((Long) responseResult.getData());
            updateNews(resultNews,(short) 9,"审核成功");
        }

    }

    @Autowired
    private IArticleClient articleClient;
    /**
     * 封装一个方法，把wmnews的属性封装成一个dto
     * 然后 调用feign接口远程调用article服务保存文章
     * @param wmNews
     * @return
     */
    private ResponseResult saveAppArticle(WmNews wmNews){
        //封装成articleDto
        ArticleDto articleDto=new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);

        //讲无法拷贝的属性进行手动赋值
        articleDto.setLayout(wmNews.getType());

        WmChannel byId = wmChannelSevice.getById(wmNews.getChannelId());
        if (byId!=null){
            articleDto.setChannelName(byId.getName());
        }

        articleDto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if(wmUser != null){
            articleDto.setAuthorName(wmUser.getName());
        }

        if(wmNews.getArticleId() != null){
            //针对的是修改news的内容后重新审核，其news中已经包含了已发布的articleId
            //如果是新发布的，第一次过审的，则不会走到这一步
            articleDto.setId(wmNews.getArticleId());
        }
        articleDto.setCreatedTime(new Date());

        //调用feign接口，实现文章保存
        ResponseResult responseResult = articleClient.saveArticle(articleDto);
        return responseResult;



    }

    /**
     * 文本审核封装方法
     * @param news 文本来源的news，作为形参方便设置news的 status 是通过还是不通过
     * @param text 要审核的文章
     * @return 审核通过返回 true 审核失败返回 false
     */
    private boolean handleTextScan(WmNews news,String text){
        boolean flag= true;
        //如果传来的文本信息为空则不用审核，直接通过
        if (text.length()==0){
            return flag;
        }
        try {
            //审核后会返回一个map，这个map中我们就关注一个key，就是suggestion的value
            // 有三种情况 ： block：审核不通过   review：机器审核无法定论   pass:审核通过
            Map textScanResult = greenTextScan.greeTextScan(text);
            if(textScanResult !=null){

                if (textScanResult.get("suggestion").equals("block")) {
                    //审核失败 将news的status设置成 2 ,并将 flag 置为false
                   updateNews(news,(short) 2,"文本审核不通过！");
                   flag=false;
                }

                if(textScanResult.get("suggestion").equals("review")){
                    flag = false;
                    updateNews(news, (short) 3, "当前文本中存在不确定内容");
                }
            }


        } catch (Exception e) {
            //出异常了也返回false 审核不成功
            flag=false;
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 图片审核封装方法
     * @param news
     * @param imageList
     * @return
     */
    private boolean handleImageScan(WmNews news,List<byte[]>imageList){
        boolean flag=true;
        if (imageList.size()==0){
            return flag;
        }
        try {
            Map map = greenImageScan.imageScan(imageList);

            if (map!=null){
                //3种情况  block  pass  review
                if (map.get("suggestion").equals("block")) {
                    //审核失败 将news的status设置成 2 ,并将 flag 置为false
                    updateNews(news,(short) 2,"图片审核不通过！");
                    flag=false;
                }

                if(map.get("suggestion").equals("review")){
                    flag = false;
                    updateNews(news, (short) 3, "当前图片中存在不确定内容");
                }

            }
        } catch (Exception e) {
            flag= false;
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 对于审核成功与否的news，都要对其的status进行修改
     * 而且设置都是共性的，所以抽成一个方法
     * @param wmNews 别修改的news
     * @param status 要修改成的状态
     * @param reason 修改状态的原因
     */
    private void updateNews(WmNews wmNews,short status ,String reason){
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsService.updateById(wmNews);
    }



}
